#import "CoreDataManager.h"
#import "FileManager.h"

@implementation CoreDataManager

SYNTHESIZE_SINGLETON_FOR_CLASS(CoreDataManager);

@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

-(id)init{
    self = [super init];
    if (self != nil) {
        fileName = [[NSString alloc] initWithFormat:@"coldjoke"];
        entityName = [[NSString alloc] initWithFormat:@"TopicDetail"];
        NSArray *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES);
        NSString *cachesDirectory = [path objectAtIndex:0];
        corePath = [[cachesDirectory stringByAppendingPathComponent:fileName] retain];
        imgPath = [[cachesDirectory stringByAppendingPathComponent:@"pics"] retain];
        [self managedObjectContext];
    }
    return self;
}

- (void)dealloc{
    PP_RELEASE(fileName);
    PP_RELEASE(entityName);
    PP_RELEASE(imgPath);
    PP_RELEASE(_managedObjectContext);
    PP_RELEASE(_managedObjectModel);
    PP_RELEASE(_persistentStoreCoordinator);
    [super dealloc];
}

- (void)saveContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            // Replace this implementation with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            Log(@"Unresolved error %@, %@", error, [error userInfo]);
        }
    }
}

#pragma mark - Core Data stack

// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}

// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:fileName withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    NSURL *storeURL = [NSURL fileURLWithPath:corePath];

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
        /*
         Replace this implementation with code to handle the error appropriately.

         abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

         Typical reasons for an error here include:
         * The persistent store is not accessible;
         * The schema for the persistent store is incompatible with current managed object model.
         Check the error message to determine what the actual problem was.

         If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.

         If you encounter schema incompatibility errors during development, you can reduce their frequency by:
         * Simply deleting the existing store:
         [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]

         * Performing automatic lightweight migration by passing the following dictionary as the options parameter:
         @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}

         Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.

         */
        Log(@"Unresolved error %@, %@", error, [error userInfo]);
    }

    return _persistentStoreCoordinator;
}

//#pragma mark - Application's Documents directory
//
//// Returns the URL to the application's Documents directory.
//- (NSURL *)applicationDocumentsDirectory
//{
//    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
//}


#pragma mark -
#pragma mark -----插入语句--- sql:insert
- (void)coredataInsert:(TopicDetailModel *)topicDetail{
    NSManagedObjectContext *context = self.managedObjectContext;
    //    NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:self.managedObjectContext];
    NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];

    //    topicContentDict = [[NSMutableDictionary alloc] init];
    //    topicPathDict = [[NSMutableDictionary alloc] init];

    [newManagedObject setValue:topicDetail.topicId forKey:@"topicId"];
    [newManagedObject setValue:topicDetail.contentDict forKey:@"contentDict"];
    [newManagedObject setValue:topicDetail.pathDict forKey:@"pathDict"];

    NSError *error = nil;
    if (![context save:&error]) {
        // Replace this implementation with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        Log(@"insert(%@) error %@, %@", topicDetail.topicId, error, [error userInfo]);
    } else {
        Log(@"insert(%@) success",topicDetail.topicId);
    }
}


#pragma mark -----删除一个--- 相当于sql:delete xx where id = xx;
//条件查询
- (BOOL)coredataTopicDetailSingleDelete:(NSString *)topicId {
    NSManagedObjectContext *context = [self managedObjectContext];
    NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
    [fetchRequest setEntity:entity];
    NSPredicate * qcondition= [NSPredicate predicateWithFormat:@"topicId == %@",topicId];
    [fetchRequest setPredicate:qcondition];
    NSError *error;
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];

    Log(@"topicId : %@, count : %d",topicId,fetchedObjects.count);
    if (fetchedObjects.count == 0 ) {
        return NO;
    }else{
        for (NSManagedObject *info in fetchedObjects){
            NSMutableDictionary *arr = [info valueForKey:@"pathDict"];
            for (NSObject *object in arr) {
                [[FileManager sharedInstance]deleteFile:[arr objectForKey:object]];
            }
            [self coredataTopicDetailDeleteObject:info];
        }
        return YES;
    }
}

#pragma mark -
#pragma mark -----删除语句--- 相当于sql:delete
//删除：NSManagedObject对象必须先取出来，用managedObjectContext删除，保存就好
-(void)coredataTopicDetailDeleteObject:(id)object{
    [self.managedObjectContext deleteObject:object];
    NSError *error = nil;
    if (![self.managedObjectContext save:&error]) {
        Log(@"delete error %@, %@", error, [error userInfo]);
    }else{
        Log(@"delete success");
    }
}

- (void)deleteAllTopicDetailForCoredata:(NSString *)sort :(NSMutableArray *)topicIds{
    if( topicIds == nil || topicIds.count == 0){
        Log(@"CoreDataManager nothing to do");
        return;
    }

    Log(@"topicIds :%@",topicIds);

    for( int i = 1 ; i < topicIds.count ; i++ ) {
        //做删除     [ids objectAtIndex:i]
        Log(@"[topicIds objectAtIndex:i]:%@",[topicIds objectAtIndex:i]);
        [self coredataTopicDetailSingleDelete:[topicIds objectAtIndex:i]];
    }
}



#pragma mark -----条件更新--- 相当于sql:update
//条件更新
- (BOOL)coredataTopicDetailUpdate:(TopicDetailModel *)topicDetail{
    NSManagedObjectContext *context = [self managedObjectContext];
    NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
    [fetchRequest setEntity:entity];
    NSPredicate * qcondition= [NSPredicate predicateWithFormat:@"topicId == %@",topicDetail.topicId];
    [fetchRequest setPredicate:qcondition];
    NSError *error;
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];

    Log(@"topicId : %@, count : %d",topicDetail.topicId,fetchedObjects.count);
    BOOL result = NO;
    if (fetchedObjects.count > 0 ) {
        for (NSManagedObject *info in fetchedObjects) {
            [info setValue:topicDetail.contentDict forKey:@"contentDict"];
            [info setValue:topicDetail.pathDict forKey:@"pathDict"];
        }
        if (![context save:&error]) {
            Log(@"update(%@) error %@, %@", topicDetail.topicId, error, [error userInfo]);
            result = NO;
        }else{
            Log(@"update(%@) success, item.count : %d, cache.count : %d",topicDetail.topicId,topicDetail.contentDict.count,topicDetail.pathDict.count);
            result = YES;
        }
    }
    return result;
}

#pragma mark -----条件查询--- 相当于sql:select
//条件查询
- (BOOL)coredataTopicDetailSelect:(TopicDetailModel *)topicDetail {
    NSManagedObjectContext *context = [self managedObjectContext];
    NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
    [fetchRequest setEntity:entity];
    NSPredicate * qcondition= [NSPredicate predicateWithFormat:@"topicId == %@",topicDetail.topicId];
    [fetchRequest setPredicate:qcondition];
    NSError *error;
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];

    Log(@"topicId : %@, count : %d",topicDetail.topicId,fetchedObjects.count);
    if (fetchedObjects.count == 0 ) {
        return NO;
    }else{
        for (NSManagedObject *info in fetchedObjects){
            topicDetail.contentDict = [[info valueForKey:@"contentDict"] retain];
            topicDetail.pathDict = [[info valueForKey:@"pathDict"] retain];
            //            Log(@"contentDict :%@",topicDetail.contentDict);
            //            Log(@"pathDict :%@",topicDetail.pathDict);
            BOOL rewrite = NO;
            if( topicDetail.contentDict == nil ){
                topicDetail.contentDict = [[NSMutableDictionary alloc]init];
                rewrite = YES;
            }
            if( topicDetail.pathDict == nil ){
                topicDetail.pathDict = [[NSMutableDictionary alloc]init];
                rewrite = YES;
            }
            if( rewrite ){
                [self coredataTopicDetailUpdate:topicDetail];
            }
            break;
        }
        return YES;
    }
}

#pragma mark -----条件更新--- 相当于sql:update
//条件更新
- (void)coredataTopicDetailPathDictUpdate {
    NSManagedObjectContext *context = [self managedObjectContext];
    NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
    [fetchRequest setEntity:entity];
//    NSPredicate * qcondition= [NSPredicate predicateWithFormat:@"topicId == %@",topicDetail.topicId];
//    [fetchRequest setPredicate:qcondition];
    NSError *error;
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
    NSLog(@"fetchObjects :%@",fetchedObjects);
    if (fetchedObjects.count > 0 ) {
        for (NSManagedObject *info in fetchedObjects) {
            [info setValue:nil forKey:@"pathDict"];
            if (![context save:&error]) {
                Log(@"update faild");
            }else{
                Log(@"update success");
            }
        }
    }
}


#pragma mark - Fetched results controller
- (NSFetchedResultsController *)fetchedResultsController {
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"topicId" ascending:NO] autorelease];
    NSArray *sortDescriptors = @[sortDescriptor];

    [fetchRequest setSortDescriptors:sortDescriptors];

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"] autorelease];
    aFetchedResultsController.delegate = self;
    _fetchedResultsController = aFetchedResultsController;

    //	NSError *error = nil;
    //	if (![self.fetchedResultsController performFetch:&error]) {
    //        // Replace this implementation with code to handle the error appropriately.
    //        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
    //	    Log(@"Unresolved error %@, %@", error, [error userInfo]);
    //	}

    return _fetchedResultsController;
}
@end
